package com.lcc.generate.mapper;

import com.alibaba.druid.util.StringUtils;
import com.lcc.generate.Config;
import com.lcc.generate.TableConfig;
import com.lcc.generate.util.MyField;
import com.lcc.generate.clazz.ClassUtils;
import com.lcc.generate.util.FileUtils;
import com.lcc.generate.util.JDBCUtil;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * mapper文件生成工具
 * 一个公共sql片段文件，一个主要文件
 */
public class MapperUtilsPG {

	public static String filePath;
	public static String mapperClassPackage = ClassUtils.mapperClassPackage;

	public static String author ;
	public static boolean coverMainMapper ; // 生成mapper时覆盖主mapper文件
	private static Config generateConfig;
	public static void generate(List<List<MyField>> fieldsArr, Config generateConfig) {
		author = generateConfig.author;
		coverMainMapper = generateConfig.coverMainMapperXml; // 生成mapper时覆盖主mapper文件
		System.out.println("----- 生成Mapper.xml");
		MapperUtilsPG.generateConfig = generateConfig;
		MapperUtilsPG.filePath = generateConfig.rootImplPath + ClassUtils.mapperXlmPath;
		for (int i = 0; i < fieldsArr.size(); i++) {
			createMapper(fieldsArr.get(i), generateConfig.generateConfigs[i]);
		}
	}


	private static final String header = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n";
	private static final String title = "\n<!--\n\tTable: #{table}\n\tComments: #{comments}\n\tAuthor: #{Author}\n-->\n\n";
	private static final String mapperHead = "<mapper namespace=\"#{namespace}\">\n\n";
	private static final String selectHead = "\t<select id=\"select\" resultMap=\"dvMap\" parameterType=\"#{parameterType}\">\n";
	private static final String insertHead = "\t<insert id=\"#{insertName}\">\n";
	private static final String updateByIdHead = "\t<update id=\"#{updateById}\" parameterType=\"#{parameterType}\">\n";
	private static final String deleteByIdHead = "\t<delete id=\"#{deleteById}\">\n";
	private static final String selectByIdHead = "\t<select id=\"#{selectById}\" resultMap=\"dvMap\">\n";
	private static final String resultMapHead = "\t<resultMap id=\"baseMap\" type=\"#{parameterType}\">\n";
	private static final String autoIdHead = "\t\t<selectKey resultType=\"java.lang.Long\" keyProperty=\"#{autoId}\" order=\"BEFORE\" >\n";
	private static final String sqlHead = "\t<sql id=\"#{sqlId}\">\n";

	private static String table;
	private static String idName;		// 主键 驼峰
	private static String idColumn;		//
	private static MyField idField;		// 类中的字段名 驼峰
	private static String namespace;
	private static String parameterType;
	private static String parameterDVType;
	private static List<String> columns;
	private static List<MyField> fields;
	private static StringBuilder columnsSql;
	private static StringBuilder columnsAll;
	private static TableConfig config;
	private static boolean ifDelete;	// 采用更新删除
	private static int tabMax = 75;


	/**
	 * 根据类生成Mapper文件
	 *
	 */
	public static void createMapper(List<MyField> fieldArr, TableConfig config) {
		//初始化
		MapperUtilsPG.table = config.getTableName(false);
		MapperUtilsPG.namespace = config.className + "Mapper" ;
		idColumn = null; idName= null; idField = null;
		MapperUtilsPG.config = config;

		parameterType = config.className;
		int index = parameterType.lastIndexOf(".");
		String name = parameterType.substring(index);
		parameterDVType = parameterType.replace(name,".dv"+name +"DV");
		String fileName = config.className.substring(config.className.lastIndexOf(".") + 1) + "Mapper.xml";
		columns = new ArrayList<>();
		fields = fieldArr;
		columnsAll = new StringBuilder();
		columnsSql = new StringBuilder();
		int t1 = 0;
		int t2 = 0;
		for (MyField field : fieldArr) {
			columnsAll.append(field.column).append(", ");
			columns.add("main." + field.column);
			columnsSql.append("main.").append(field.column).append(", ");
			if (columnsAll.substring(t1).length() > 110) {
				columnsAll.append("\n\t\t");
				t1 = columnsAll.lastIndexOf("\n") + 1;
			}
			if (columnsSql.substring(t2).length() > 110) {
				columnsSql.append("\n\t\t");
				t2 = columnsSql.lastIndexOf("\n") + 1;
			}
			if(field.column.equals(config.primaryKey)){
				idField = field;
				idColumn = field.column;
				idName = field.name;
			}
			if(field.column.equals("if_delete")){
				ifDelete = true;
			}

		}
		int i = columnsAll.lastIndexOf(",");
		columnsAll.delete(i, columnsAll.length());
		i = columnsSql.lastIndexOf(",");
		columnsSql.delete(i, columnsSql.length());

		String title0 = header;
//				title.replace("#{table}", table)
//						.replace("#{comments}", config.tableComment)
//						.replace("#{Author}", author);
		//拼装
		String file0Str = title0 + getMapper0();

		String fileName2 = fileName.replace("Mapper.xml", ".xml");
		File file0path = new File(filePath + "/generate");
		if(!file0path.exists()){
			file0path.mkdirs();
		}
		System.out.println("生成：" + fileName2);
		FileUtils.write(new File(file0path, fileName2), file0Str);

		String fileStr = title0 + getMapper();
		File filePath = new File(MapperUtilsPG.filePath);
		if(!filePath.exists()) {
			filePath.mkdirs();
		}
		File file = new File(filePath, fileName);
		if(!file.exists() || coverMainMapper){
			System.out.println("生成：" + fileName);
			FileUtils.write(new File(MapperUtilsPG.filePath, fileName), fileStr);

		}
	}

	private static String getMapper0() {
		return mapperHead.replace("#{namespace}", parameterType) +
				resultMap() +
				columnsAll() +
				whereBaseAll() +
				setAll() +
				insertAll() +
				whereLikeAll() +
				whereListAll() +
				whereTimeAll() +
				orderByInList() +
				"</mapper>";
	}

	private static String getMapper() {
		int index = parameterType.lastIndexOf(".");
		String name = parameterType.substring(index);
		namespace = mapperClassPackage + name + "Mapper";
		return mapperHead.replace("#{namespace}", namespace) +
//				"<!--\n" +
//				"\t父mapperId：" + parameterType+"\n" +
//				"-->\n\n" +
				"\t<resultMap id=\"dvMap\" type=\"" + parameterDVType +
				"\" extends=\"" + parameterType +
				".baseMap\" autoMapping=\"true\"></resultMap>\n\n"+
				select() +
				insert() +
				update() +
				delete() +
				"</mapper>";
	}

	private static StringBuilder resultMap() {
		StringBuilder resultMap = new StringBuilder();
		resultMap.append(resultMapHead.replace("#{parameterType}", parameterDVType));
		for (MyField field : fields) {
			if(idName !=null&& idName.equals(field.name)){
				resultMap.append("\t\t<id")
						.append("     property=\"").append(field.name).append("\" ")
						.append(getTabNumResult(15, field.name))
						.append("column=\"").append(field.column).append("\" ")
						.append(getTabNumResult(14, field.column))
						.append("jdbcType=\"").append(getJdbcType(field)).append("\"/>\n");
				break;
			}
		}
		for (MyField field : fields) {
			if(idName == null || !idName.equals(field.name)){
				resultMap.append("\t\t<result")
						.append(" property=\"").append(field.name).append("\" ")
						.append(getTabNumResult(15, field.name))
						.append("column=\"").append(field.column).append("\" ")
						.append(getTabNumResult(14, field.column))
						.append("jdbcType=\"").append(getJdbcType(field)).append("\"")
						.append(ifStr(field.classType.equals("BigDecimal"), " typeHandler=\"com.lcc.lynx.jdbc.handle.DecimalTypeHandler\""))
						.append("/>\n");
			}
		}
		resultMap.append("\t</resultMap>\n\n");
		return resultMap;
	}

	private static StringBuilder columnsAll() {
		StringBuilder select = new StringBuilder();
		select.append(sqlHead.replace("#{sqlId}", "selectAll"))
				.append("\t\t").append(columnsSql).append("\n")
				.append("\t</sql>\n\n");
		return select;
	}

	private static StringBuilder whereBaseAll() {
		StringBuilder where = new StringBuilder();
		where.append(sqlHead.replace("#{sqlId}", "whereBaseAll"));
		for (MyField field : fields) {

			where.append("\t\t<if test=\"").append(field.name).append(" != null");
			if (field.isString) {
				where.append(" and ").append(field.name).append(" != ''");
			}
			if (field.isTime) {
				where.append("\">")
						.append(getTabNum(field, 0)).append("and main.").append(field.column).append("::date = ")
						.append("to_date(#{").append(field.name)
						.append(", jdbcType=DATE, typeHandler=com.lcc.lynx.jdbc.handle.Date2StringTypeHandler}, 'yyyy-mm-dd')</if>\n");
			} else {
				where.append("\">")
						.append(getTabNum(field, 0)).append("and main.").append(field.column).append(" = ")
						.append(val(field.name, field)).append("</if>\n");
			}
		}
		where.append("\t\t${tp.enhanceConditions}\n");
		where.append("\t</sql>\n\n");
		return where;
	}
	private static StringBuilder setAll() {

		StringBuilder set = new StringBuilder();

		set.append(sqlHead.replace("#{sqlId}", "setArg0All"));
		for (MyField field : fields) {
			if(field == idField){
				continue ;
			}
			set.append("\t\t<if test=\"a0.").append(field.name).append(" != null");
			if(field.isString){
				set.append(" and a0.").append(field.name).append(" != ''");
			}
			String tabs;
			if(!field.required && (field.isString || field.isNumber)){
				set.append(" or tp.").append(field.name).append("Must");
				tabs = getTabNum3(field,3);
			}else {
				tabs = getTabNum(field,3);
			}
			set.append("\">")
					.append(tabs).append(field.column).append(" = ")
					.append(valA0(field.name, field))
					.append(",</if>");
			if(field.name.equals("updateTime")){
				set.append("<if test=\"a0.updateTime == null\">update_time = now(),</if>");
			}
			if(field.name.equals("update_time")){
				set.append("<if test=\"a0.update_time == null\">update_time = now(),</if>");
			}
			set.append("\n");
		}
		set.append("\t</sql>\n\n");
		return set;
	}

	private static void setUpdateAll(StringBuilder set) {
		set.append(sqlHead.replace("#{sqlId}", "setUpdateAll"));
		for (MyField field : fields) {
			if(field.name.equals("updateTime")){
				set.append("\t\t").append(field.column).append("=now(),\n");
				continue;
			}
			set.append("\t\t<if test=\"").append(field.name).append(" != null");
			if(field.isString){
				set.append(" and ").append(field.name).append(" != ''");
			}
			set.append("\">")
					.append(getTabNum(field,0)).append(field.column.substring(5)).append(" = ")
					.append(val(field.name, field))
					.append(",</if>\n");
		}
		set.append("\t</sql>\n\n");
	}

	private static StringBuilder insertAll() {
		StringBuilder insert = new StringBuilder();
		insert.append("\t<sql id=\"insertSetAll\"><trim suffixOverrides=\",\" >\n");
		insert.append("\t\t").append(getColumnsAll())
				.append("\n\t</trim></sql>\n\n");
		insert.append("\t<sql id=\"insertValueAll\"><trim suffixOverrides=\",\" >\n");
		insert.append("\t\t").append(getFieldsSql2()).append("\n")
				.append("\t</trim></sql>\n\n");
		return insert;
	}

	private static StringBuilder select() {
		StringBuilder select = new StringBuilder();
		select.append(selectHead.replace("#{parameterType}", parameterDVType))
				.append("\t\tselect <include refid=\"").append(parameterType).append(".selectAll\"/>")
				.append("\n\t\tfrom ").append(table).append(" main\n")
				.append("\t\t<where>").append(ifStr(ifDelete," main.if_delete = 0")).append("\n")
				.append("\t\t\t<include refid=\"").append(parameterType).append(".whereAll\"/>").append("\n")
				.append("\t\t</where>\n\t\t<include refid=\"").append(parameterType).append(".orderByAll\"/>").append("\n");

		select.append("\t</select>\n\n");
		return select;
	}

	private static StringBuilder insert() {
		StringBuilder insert = new StringBuilder();
		insert.append(insertHead.replace("#{insertName}", "insert"));
		if(idName != null) {
			insert.delete(insert.length() - 2, insert.length());
			insert.append(" useGeneratedKeys=\"true\" keyProperty=\"").append(idName).append("\" keyColumn=\"").append(idColumn).append("\">\n");
		}
		insert.delete(insert.length() - 1, insert.length());
		insert.append("\n\t\tinsert into ").append(table).append(" (<include refid=\"").append(parameterType).append(".insertSetAll\"/>)\n")
				.append("\t\tvalues <foreach collection=\"list\" item=\"item\" separator=\",\">\n")
				.append("\t\t\t(<include refid=\"").append(parameterType).append(".insertValueAll\"/>)\n")
				.append("\t\t</foreach>\n")
				.append("\t</insert>\n\n");
		return insert;
	}

	private static StringBuilder update() {
		StringBuilder update = new StringBuilder();
		update.append(updateByIdHead.replace("#{updateById}", "update")
				.replace("#{parameterType}", parameterDVType))
				.append("\t\tupdate ").append(table).append(" main <set><include refid=\"").append(parameterType).append(".setArg0All\"/>").append("</set>\n")
				.append("\t\twhere ").append("<trim ").append(ifDelete ? "prefix=\"main.if_delete = 0\"" : "prefixOverrides=\"and\"").append(">\n")
				.append("\t\t\t<include refid=\"").append(parameterType).append(".whereBaseAll\"/>").append("\n")
				.append("\t\t</trim>\n\t</update>\n\n");
		return update;
	}

	private static StringBuilder delete() {
		StringBuilder delete = new StringBuilder();
		delete.append(deleteByIdHead.replace("#{deleteById}", "delete"));
		if(ifDelete){
			delete.append("\t\tupdate ").append(table).append(" main set if_delete = 1");
		}else{
			delete.append("\t\tdelete from ").append(table).append(" main");
		}
		delete.append("\n\t\twhere <trim ").append(ifDelete ? "prefix=\"main.if_delete = 0\"" : "prefixOverrides=\"and\"").append(">\n");
		if(idName != null){
			delete.append("\t\t\t<include refid=\"").append(parameterType).append(".whereListAll\"/>").append("\n");
		}else{
			delete.append("\t\t\t<include refid=\"").append(parameterType).append(".whereBaseAll\"/>").append("\n");
		}
		delete.append("\t\t</trim>\n\t</delete>\n\n");

		return delete;
	}


	private static StringBuilder whereLikeAll() {
		StringBuilder where = new StringBuilder();
		where.append(sqlHead.replace("#{sqlId}", "whereLikeAll"));
		for (MyField field : fields) {
			if(!field.isString) continue;
			if(!field.searchType.contains("like")) continue;
			where.append("\t\t<if test=\"tp.").append(field.name).append("LikeL != null");
			where.append(" and tp.").append(field.name).append("LikeL != ''\">");
			where.append(getTabNum(field,8)).append("and main.").append(field.column)
					.append(" like concat(").append(valTp(field.name, "LikeL"))
					.append(",'%')</if>\n");

			where.append("\t\t<if test=\"tp.").append(field.name).append("Like != null");
			where.append(" and tp.").append(field.name).append("Like != ''\">");
			where.append(getTabNum(field,7)).append("and main.").append(field.column)
					.append(" like concat('%',").append(valTp(field.name, "Like"))
					.append(",'%')</if>\n");
		}
		where.append("\t</sql>\n\n");
		return where;
	}

	private static StringBuilder whereListAll() {
		StringBuilder where = new StringBuilder();
		where.append(sqlHead.replace("#{sqlId}", "whereListAll"));
		if(idName != null && !idName.equals("id")) {
			where.append("\t\t<if test=\"tp.idInList != null and tp.idInList.size() > 0\">")
					.append(getTabNumTimeStr("id", 11.5F)).append("and main.").append(idColumn)
					.append(" in ( <foreach collection=\"tp.idInList\" item=\"item\" separator=\",\" >")
					.append(valItem(idField)).append("</foreach>) </if>\n");
		}
		for (MyField field : fields) {
			if(field.isTime) continue;
			if(!field.searchType.contains("list") && !field.name.equals(idName)) continue;
			where.append("\t\t<if test=\"tp.").append(field.name).append("InList != null");
			where.append(" and tp.").append(field.name).append("InList.size() > 0\">");
			where.append(getTabNumTimeStr(field.name, 11.5F)).append("and main.").append(field.column)
					.append(" in ( <foreach collection=\"tp.").append(field.name).append("InList\" item=\"item\" separator=\",\" >")
					.append(valItem(field))
					.append("</foreach> ) </if>\n");
		}
		where.append("\t</sql>\n\n");
		return where;
	}

	private static StringBuilder whereTimeAll() {
		StringBuilder where = new StringBuilder();
		where.append(sqlHead.replace("#{sqlId}", "whereTimeAll"));
		for (MyField field : fields) {
			if(!field.isTime) continue;
			if(!field.searchType.contains("time")) continue;
			where.append("\t\t<if test=\"tp.").append(field.name).append("Start != null");
			where.append(" and tp.").append(field.name).append("Start != ''\">");
			where.append(getTabNumTimeStr(field.name,8)).append("and main.").append(field.column)
					.append(" &gt;= to_date(").append(valTp(field.name, "Start"))
					.append(", 'yyyy-mm-dd')</if>\n");

			where.append("\t\t<if test=\"tp.").append(field.name).append("End != null");
			where.append(" and tp.").append(field.name).append("End != ''\">");
			where.append(getTabNumTimeStr(field.name,8)).append("    and main.").append(field.column)
					.append(" &lt; to_date(").append(valTp(field.name, "End"))
					.append(", 'yyyy-mm-dd') + 1</if>\n");
		}
		where.append("\t</sql>\n\n");
		return where;
	}

	private static StringBuilder orderByInList() {
		StringBuilder where = new StringBuilder("\t<sql id=\"orderByAll\"><trim prefix=\"order by\"><if test=\"tp.orderByInList != null and tp.orderByInList.size() > 0\"><foreach collection=\"tp.orderByInList\" item=\"item\" separator=\",\">\n");
		for (MyField field : fields) {
			if(!field.isOrder) continue;
			where.append(String.format("\t\t<if test=\"item == '%s'\">%smain.%s</if>\n", field.name, getOrder2(field, 0), field.column));
			where.append(String.format("\t\t<if test=\"item == '%s desc'\">%smain.%s desc</if>\n", field.name, getOrder2(field, 5), field.column));
		}
		where.append("\t</foreach></if></trim></sql>\n\n");
		where.append("\t<sql id=\"whereAll\">\n")
				.append("\t\t<include refid=\"").append(parameterType).append(".whereBaseAll\"/>\n")
				.append("\t\t<include refid=\"").append(parameterType).append(".whereLikeAll\"/>\n")
				.append("\t\t<include refid=\"").append(parameterType).append(".whereListAll\"/>\n")
				.append("\t\t<include refid=\"").append(parameterType).append(".whereTimeAll\"/>\n")
				.append("\t</sql>\n\n");
		return where;
	}



	private static StringBuilder getColumnsAll() {
		StringBuilder columns = new StringBuilder();
		int i = 0;
		for (MyField field : fields) {
			if(field.column.equals(idColumn)) {
				columns.insert(0, field.column + ",\n\t\t");
				continue;
			}

			if(field.required && !field.isHasDefaultValue) {
				columns.append(field.column).append(", ");
				if(++i % 6 == 0){
					columns.append("\n\t\t");
				}
			}
		}

		for (MyField field : fields) {
			if(field.column.equals(idColumn)) continue;
			if(field.required && !field.isHasDefaultValue) continue;
			if(field.isString){
				columns.append("\n\t\t<if test=\"list.size>1 or list[0].").append(field.name).append("!=null")
						.append(ifStr(field.isString, " and list[0]." + field.name + "!=''")).append("\">")
						.append(getTabNum(15, field, 6)).append(field.column).append(",</if>");
			}else{
				columns.append("\n\t\t<if test=\"list.size>1 or list[0].").append(field.name).append(" != null")
						.append(ifStr(field.isString, " and list[0]." + field.name + " != ''")).append("\">")
						.append(getTabNum(15, field, 8)).append(field.column).append(",</if>");
			}

		}
		return columns;
	}
	private static StringBuilder getFieldsSql2() {
		StringBuilder sb = new StringBuilder();
		int i = 0;
		for (MyField field : fields) {
			if(field.column.equals(idColumn)){
				String autoIdStr;
				if(!StringUtils.isEmpty(config.sequence)){
					autoIdStr = "nextVal('" + config.sequence + "')";
				}else if(field.isHasDefaultValue){
					autoIdStr = "default";
				}else{
					autoIdStr = "nextVal('" + config.getTableName(false) + "_" + idColumn + "_seq')";
				}
				StringBuilder sb2 = new StringBuilder();
				sb2.append("<if test=\"item.").append(field.name).append(" != null\">")
						.append(val(field.name, field, "item.")).append("</if>")
						.append("<if test=\"item.").append(field.name).append(" == null\">")
						.append(autoIdStr).append("</if>").append(",\n\t\t");
				sb.insert(0, sb2);
				continue;
			}
			if(field.required && !field.isHasDefaultValue){
				sb.append(valInsert(field.name, "item.")).append(", ");
				if(++i % 6 == 0){
					sb.append("\n\t\t");
				}
			}
		}
		for (MyField field : fields) {
			if(field.column.equals(idColumn)) continue;
			if(field.required && !field.isHasDefaultValue) continue;
            if(field.isString){
                sb.append("\n\t\t<if test=\"list.size>1 or item.").append(field.name).append(" != null")
                        .append(" and item." + field.name + " != ''").append("\">")
                        .append(getTabNum(13, field,6)).append(val(field.name, field, "item.")).append(",</if>");
                if(field.isHasDefaultValue){
                    sb.append("<if test=\"list.size>1 and (item.").append(field.name).append(" == null")
                            .append(" or item." + field.name + " == '')").append("\"> default,</if>");
                }
            }else{
                sb.append("\n\t\t<if test=\"item.").append(field.name).append(" != null").append("\">")
                        .append(getTabNum(0, field,5)).append(val(field.name, field, "item.")).append(",</if>");
                if(field.isHasDefaultValue){
                    sb.append("<if test=\"list.size>1 and item.").append(field.name).append(" == null").append("\"> default,</if>");
                }
            }
		}
		return sb;
	}
	private static StringBuilder getFieldsSql() {
		StringBuilder sb = new StringBuilder();
		String[] split = columnsAll.toString().split("\n");
		List<Integer> nNums = new ArrayList<>();
		int num = 0;
		if(split.length > 1){
			for (int i = 0; i < split.length - 1; i++) {
				num += split[i].split(",").length -1;
				nNums.add(num);
			}
		}
		for (int i = 0; i < fields.size(); i++) {
			if(i!=0 && nNums.contains(i)){
				sb.append("\n\t\t");
			}
			MyField field = fields.get(i);
			if(field.column.equals(idColumn) && !field.isHasDefaultValue){
				String autoIdStr;
				if(generateConfig.dbType.equals("mysql") || "null".equals(config.sequence)){
					autoIdStr = "null";
				}else if(!StringUtils.isEmpty(config.sequence)){
					autoIdStr = "nextVal('" + config.sequence + "')";
				}else{
					autoIdStr = String.format("nextVal('%s_%s_seq')", table, idColumn);
				}
				if(i!=0){ sb.append("\n\t\t"); }
				sb.append("<if test=\"item.").append(fields.get(i).name).append(" != null\">")
						.append(val(field.name, field, "item.")).append("</if>")
						.append("<if test=\"item.").append(fields.get(i).name).append(" == null\">")
						.append(autoIdStr).append("</if>").append(", ");
				continue;
			}
			if (field.name.equals("createTime") || field.name.equals("updateTime")) {
				sb.append("now(), ");
				continue;
			}
			if(field.isHasDefaultValue){
				if(i!=0){ sb.append("\n\t\t"); }
				sb.append("<if test=\"item.").append(fields.get(i).name).append(" != null\">")
						.append(val(field.name, field, "item.")).append("</if>")
						.append("<if test=\"item.").append(fields.get(i).name).append(" == null\">")
						.append("default</if>").append(", ");
			}else {
				sb.append(val(field.name, field, "item.")).append(", ");

			}
		}
		sb.delete(sb.length()-2,sb.length());
		return sb;
	}

	private static String getJdbcType(MyField field){
		if(field.isNumber){
			return "NUMERIC";
		}else if(field.isTime){
			return "TIMESTAMP";
		}else if(field.isBool){
			return "BOOLEAN";
		}else{
			return "VARCHAR";
		}
	}

	private static String val(String str) {
		return "#{"+ str +"}";
	}
	private static String val(String str ,MyField field) {
		return "#{"+ str +", jdbcType="+ getJdbcType(field)+"}";
	}
	private static String val(String str ,MyField field, String prefix) {
		return "#{"+ prefix + str +", jdbcType="+ getJdbcType(field)+"}";
	}
	private static String valInsert(String str, String prefix) {
		return "#{"+ prefix + str +"}";
	}
	private static String valA0(String str ,MyField field) {
		return "#{a0."+ str +", jdbcType="+ getJdbcType(field)+"}";
	}
	private static String valTp(String str, String name) {
		return "#{tp."+ str  + name +", jdbcType=VARCHAR}";
	}

	private static String valItem(MyField field) {
		if(field.isString) {
			return "#{item, jdbcType=VARCHAR}";
		}else if(field.type.equals("decimal")){
			return "#{item, jdbcType=BigDecimal, typeHandler=com.lcc.lynx.jdbc.handle.String2BigDecimalTypeHandler}";
		}else {
			return "#{item, jdbcType=BIGINT, typeHandler=com.lcc.lynx.jdbc.handle.String2LongTypeHandler}";
		}
	}

	private static String valId(MyField field, String name) {
		if(field.isString) {
			return "#{"+name+", jdbcType=VARCHAR}";
		}else if(field.type.equals("decimal")){
			return "#{" + name + "} :: NUMERIC";
		}else {
			return "#{" + name + "} :: BIGINT";
		}
	}

	/**
	 *
	 * @param field
	 * @param pri 字段名前置 如 a0.username 前缀为a0. 则 pri=3
	 * @return
	 * @author lcc
	 * @date 2025/6/20 10:34
	 */
	private static String getTabNum(int start , MyField field, float pri) {
		int len = start;
		if(field.isString){
			len += 31 + field.name.length()*2 + pri*2;
		}else{
			len += 20 + field.name.length() + pri;
		}
		StringBuilder t = new StringBuilder();
		int max = tabMax;
		if(len < max){
			t.append(" ".repeat(Math.max(0, max - len)));
		}
		return t.toString();
	}

	private static String getTabNum(MyField field, int pri) {
		return getTabNum(0, field, pri);
	}

	private static String getTabNumResult(int start, String str) {
		int len = start + str.length();
		StringBuilder t = new StringBuilder();
		int max = 37;
		if(len < max){
			t.append(" ".repeat(Math.max(0, max - len)));
		}
		return t.toString();
	}

	private static String getTabNum3(MyField field, int pri) {
		int len = 0;
		if(field.isString) {
			len = 39 + field.name.length() * 3 + pri * 3;
		}else if(field.isNumber){
			len = 28 + field.name.length()*2 + pri*2;
		}else{
			len = 20 + field.name.length() + pri;
		}
		StringBuilder t = new StringBuilder();
		int max = tabMax;
		if(len < max){
			t.append(" ".repeat(Math.max(0, max - len)));
		}
		return t.toString();
	}

	private static String getTabNumTimeStr(String name, float pri) {
		int len = (int) (31 + name.length()*2 + pri*2);
		StringBuilder t = new StringBuilder();
		int max = tabMax;
		if(len < max){
			t.append(" ".repeat(Math.max(0, max - len)));
		}
		return t.toString();
	}

	// 不判断字符串
	private static String getOrder2(MyField field, int pri) {
		int len = 0;
		len = 22	 + field.name.length() + pri;
		StringBuilder t = new StringBuilder();
		int max = tabMax;
		if(len < max){
			t.append(" ".repeat(Math.max(0, max - len)));
		}
		return t.toString();
	}
	public static String ifStr(boolean b, String str){
		return !b || str==null ?"":str;
	}
}
